from psychometry.models import Questionnaire, Analysis, Psychometry
from psychometry.serializers import PsychometrysSerializer, PsychometrySerializer
from user.models import User
from utils import custom_exceptions as cex
from utils.pagination import CustomPaginator
from utils.tools import json_to_dl, dl_to_json, get_random

MAP_RANGE = [
	[1.85, 3.5, 5],  # 躯体化
	[2.2, 3.5, 5],  # 强迫症状
	[2.16, 3.5, 5],  # 人际关系敏感
	[2.09, 3.5, 5],  # 抑郁
	[1.82, 3.5, 5],  # 焦虑
	[2.04, 3.5, 5],  # 敌对
	[1.66, 3.5, 5],  # 恐怖
	[2, 3.5, 5],  # 偏执
	[1.71, 3.5, 5],  # 精神病性
	[2, 3.5, 5],  # 其他
	[160],  # 总分
	[1.87],  # 总均分
	[43]  # 阳性项目数
]
MAP_SUB_NUM = [
	[1, 4, 12, 27, 40, 42, 48, 49, 52, 53, 56, 58],  # 躯体化
	[3, 9, 10, 28, 38, 45, 46, 51, 55, 65],  # 强迫症状
	[6, 21, 34, 36, 37, 41, 61, 69, 73],  # 人际关系敏感
	[5, 14, 15, 20, 22, 26, 29, 30, 31, 32, 54, 71, 79],  # 抑郁
	[2, 17, 23, 33, 39, 57, 72, 78, 80, 86],  # 焦虑
	[11, 24, 63, 67, 74, 81],  # 敌对
	[13, 25, 47, 50, 70, 75, 82],  # 恐怖
	[8, 18, 43, 68, 76, 83],  # 偏执
	[7, 16, 35, 62, 77, 84, 85, 87, 88, 90],  # 精神病性
	[19, 44, 59, 60, 64, 66, 89]  # 其他
]

def score_map(sub_num, score):
	index = len(MAP_RANGE[sub_num])
	for i,range_num in enumerate(MAP_RANGE[sub_num]):
		if score <= range_num: index = i
	return index

def get_sub_score(answers: [int]):
	sub_score = [0.0] * len(MAP_SUB_NUM)
	if len(answers) != 90: raise cex.QueryParamsErrorException()
	total, avg, positive = 0, 0.0, 0
	for i, q_list in enumerate(MAP_SUB_NUM):
		for q_num in q_list:
			sub_score[i] += answers[q_num-1]
			if answers[q_num-1] >= 2: positive += 1
		total += int(sub_score[i])
		sub_score[i] = round(sub_score[i] / len(q_list), 2)
		avg += sub_score[i]
	avg = round(avg / len(MAP_SUB_NUM), 2)
	sub_score += [total, avg, positive]
	return sub_score

class PsychometryService:
	def __init__(self):
		self.psychometry_set = Psychometry.objects.get_queryset()
		self.questionnaire_set = Questionnaire.objects.get_queryset()
		self.analysis_set = Analysis.objects.get_queryset()
		self.psychometry_serializer = PsychometrySerializer
		self.psychometrys_serializer = PsychometrysSerializer

	def create_psychometry(self, uid, qid):
		user = User.objects.get(uid=uid)
		questionnaire = self.questionnaire_set.get(id=qid)
		psychometry = Psychometry(user=user, questionnaire=questionnaire)
		psychometry.create()
		return self.psychometry_serializer(psychometry).data

	def answer(self, pid, answers):
		try: psychometry = self.psychometry_set.get(id=pid)
		except Psychometry.DoesNotExist:
			raise cex.QueryParamsErrorException()
		if psychometry.answer_time is not None:
			raise cex.NotAllowedOptionException()
		answers_list = json_to_dl(answers)
		sub_score = get_sub_score(answers_list)
		analysis = []
		for i,score in enumerate(sub_score):
			score_code = score_map(i, score)
			code = (i<<2) + score_code
			analysis_model = self.analysis_set.get(code=code)
			analysis.append({
				"score": score,
				"title": analysis_model.title,
				"explain": analysis_model.explain,
				"suggest": analysis_model.suggest
			})
		psychometry.answer_questions(answers_list, analysis)
		return self.psychometry_serializer(psychometry).data
	
	def get_psychometrys(self, uid, limit, offset):
		psychometrys = self.psychometry_set.filter(user_id=uid)
		paginator = CustomPaginator(psychometrys, limit)
		paginator.get_page(offset=offset)
		return paginator.paged_data(self.psychometrys_serializer)
	
	def get_psychometry(self, pid):
		try: psychometry = self.psychometry_set.get(id=pid)
		except Psychometry.DoesNotExist: raise cex.QueryParamsErrorException()
		return self.psychometry_serializer(psychometry).data
	
	def delete_psychometry(self, pid):
		try: psychometry = self.psychometry_set.get(id=pid)
		except Psychometry.DoesNotExist: raise cex.NotAllowedOptionException()
		psychometry.delete()


if __name__ == "__main__":
	
	pass
	